#include <jni.h>
#include "gsyncer.h"
#include "watcher.h"
#include <vector>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <string>
#include <unistd.h>
#include <iostream>
#include <cstdlib>
#include <stdio.h>
#include <pthread.h>
#include <cstring>
#include <dirent.h>
#include <signal.h>
using namespace std;

//void login(string& name, string& pwd, string& main_dir,
//			vector<string>& all_path, Watcher& gsyncer);

Watcher *pWatcher=NULL;
Watcher gsyncer;
vector<string> all_path;

void* watch_thread(void* gsyncer)
{
  ((Watcher*)gsyncer)->watch(all_path);
}
void* process_thread(void* gsyncer)
{
	((Watcher*)gsyncer)->process_events();
}

void dir_search(vector<string>& watch_list, string& pre_path)
{
	DIR * pre;

	if( (pre = opendir(pre_path.c_str())) == NULL )
	{
		perror("opdir");
		exit(-1);
	}

	struct dirent *guy = readdir(pre);
	struct stat file_info;

	while( guy != NULL )
	{
		if( strcmp(guy->d_name,".") == 0 || strcmp(guy->d_name,"..") == 0 )
		{
			guy = readdir(pre);
			continue;
		}

		string name_temp = pre_path + "/";
		name_temp += guy->d_name;

		if( stat(name_temp.c_str(),&file_info) < 0 )
		{
			perror("stat");
			exit(-1);
		}

		if( S_ISDIR(file_info.st_mode) )
		{
			watch_list.push_back(name_temp);
			dir_search(watch_list,name_temp);
		}

		guy = readdir(pre);
	}
}
#ifdef __cplusplus 
extern "C"{
#endif
/*
 * Class:     syncer
 * Method:    reg
 * Signature: (Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_syncer_reg
(JNIEnv *env, jobject obj, jstring usr , jstring dire)
{
  const char *str;
  str = (env)->GetStringUTFChars(usr, NULL);
  if (str == NULL) {
    return NULL; /* OutOfMemoryError already thrown */
  }
  const char *dir;
  dir =(env)->GetStringUTFChars( dire,NULL);
  if(dir == NULL)
  {
    return NULL;
  }
  cout<<str<<" "<<dir<<endl;
  if (connect(gsyncer.ctl_sock,(struct sockaddr*)&gsyncer.srv_ctl, 
				sizeof(gsyncer.srv_ctl)) < 0 )
  {
    perror("connect");
    exit(-1);
  }
  
  string pwd("tem");
  struct usr_info info;
  info.type = REG;
  strncpy(info.usr,str,USR_LEN-1);
  strncpy(info.pwd,pwd.c_str(),PWD_LEN-1);
  
  //发送给服务器
  if( writen(gsyncer.ctl_sock,&info,sizeof(struct usr_info)) < 0 )
  {
    perror("write");
    exit(-1);
  }
  
  //读取服务器的应答
  int8_t reply;
  if( readn(gsyncer.ctl_sock,&reply,sizeof(reply)) < 0 )
  {
    perror("read");
    exit(-1);
  }
  if(reply==-1)
    return -1;
  string main_dir(dir);
  if( mkdir(main_dir.c_str(),0766) < 0 )
  {
    perror("mkdir");
    exit(-1);
  }
  
  if( chdir(main_dir.c_str()) < 0 )
  {
    perror("chdir");
    exit(-1);
  }
  
  all_path.push_back(main_dir);
		
  return 0;
}

/*
 * Class:     syncer
 * Method:    login
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_syncer_login
(JNIEnv * env , jobject obj, jstring usrr , jstring pwdd, jstring dire)
{
  const char *usr;
  usr =(env)->GetStringUTFChars(usrr, NULL);
  //usr = (char*)(*env)->GetStringUTFChars(env, serverName, NULL);
  if (usr == NULL) {
    return NULL; /* OutOfMemoryError already thrown */
  }
  const char*pwd;
  pwd = (env)->GetStringUTFChars( pwdd,NULL);
  if(pwd == NULL)
  {
    return NULL;
  }
  const char *dir;
  dir = (env)->GetStringUTFChars( dire,NULL);
  if(dir == NULL)
  {
    return NULL;
  }

  

  struct usr_info info;
  info.type = LOGIN;
  strncpy(info.usr,usr,USR_LEN-1);
  strncpy(info.pwd,pwd,PWD_LEN-1);
  
  //发送给服务器
  if( writen(gsyncer.ctl_sock,&info,sizeof(struct usr_info)) < 0 )
  {
    perror("write");
    exit(-1);
  }
  
  //读取服务器的应答
  int8_t reply;
  if( readn(gsyncer.ctl_sock,&reply,sizeof(reply)) < 0 )
  {
    perror("read");
    exit(-1);
  }
  
  if( reply != 0 )
  {
    //	cout << "用户名不存在或者密码错误" << endl;
    printf("用户名不存在或者密码错误\n");
    exit(-1);
  }
  
  string main_dir(dir);
  if( chdir(main_dir.c_str()) < 0 )
  {
    perror("chdir");
    exit(1);
  }
  
  //删除本地文件  没有必要删除本地的 如果有的 直接解压就覆盖了 如果是后来添加的  下次同步有可能给同步过去 
  //system("rm -r -f *");
  
  //接收&解压
  int fd_zip;
  if( (fd_zip = open("gsyncer.zip",O_WRONLY|O_CREAT,0766)) < 0 )
  {
    perror("open");
    exit(-1);
  }
  
  file_rcv(fd_zip,gsyncer.ctl_sock); 
  close(fd_zip);
  
  system("unzip -q gsyncer.zip ; rm gsyncer.zip");
  
  //找出所有文件夹，存入all_path
  all_path.push_back(main_dir);
  dir_search(all_path,main_dir);
  
  return 0;
    
}
/*
 * Class:     syncer
 * Method:    setDIR
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_syncer_setDIR
  (JNIEnv  * env, jobject obj, jstring dir)
{
  const char *str;
  str = (env)->GetStringUTFChars( dir,0);
  if (str == NULL) {
    return NULL; /* OutOfMemoryError already thrown */
  }
  return 0;
}

/*
 * Class:     syncer
 * Method:    sync
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_syncer_sync
  (JNIEnv * env , jobject obj, jstring usrr, jstring pwdd, jstring dire)
{
  const char*usr;
  usr  = (env)->GetStringUTFChars(usrr, 0);
  if (usr == NULL) {
    return NULL; /* OutOfMemoryError already thrown */
  }
  const char *pwd;
  pwd = (env)->GetStringUTFChars( pwdd, 0);
  if(pwd ==NULL)
  {
    return NULL;
  }
  const char*dir;
  dir = (env)->GetStringUTFChars( dire,0);
  if(dir == NULL)
  {
    return NULL;
  }

  
  string usr_name(usr),usr_pwd(pwd),main_dir(dir);
  
  printf("%s\n",main_dir.c_str());
    
  //login(usr_name,usr_pwd,main_dir,all_path, gsyncer);
  gsyncer.set_usr_info(usr_name,usr_pwd);
  
  pWatcher = &gsyncer;
  
  pthread_t tid_process, tid_watch;
  
  //处理事件线程
  if( pthread_create(&tid_process,NULL,process_thread,&gsyncer) < 0 )
  {
    perror("pthread_create");
    exit(-1);
  }
  //监控线程
  if( pthread_create(&tid_watch,NULL,watch_thread,&gsyncer) < 0 )
  {
    perror("pthread_create");
    exit(-1);
  }
  return 0; 
}
#ifdef __cplusplus
}
#endif
